package com.whstudio.common.memory.pool;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.whstudio.util.mvc.action.ActionUtil;
import com.whstudio.util.string.StrUtil;
import com.whstudio.util.string.SystemInfo;
import com.whstudio.util.xml.CDocument;
import com.whstudio.util.xml.IDocument;

public abstract class GenericPool<T> {
	private IDocument conf;
	private int minCount,maxCount,step;
	protected List<T> inPool,outPool;
	private String className=null;
	
	protected GenericPool(String path,String className){
		this.className=className;
		beforeInit();
		String uri=null;
		if(ActionUtil.userDir==null){
			uri=SystemInfo.USER_DIR+"\\WebRoot\\"+StrUtil.slashToBackslash(path);
		}else{
			uri=ActionUtil.userDir+path;
		}
		if(StrUtil.isUrl(uri)){
			this.conf=CDocument.getIDocFromUri(uri);
		}else{
			this.conf=CDocument.getIDocFromFile(uri);
		}
		initParams();
	}
	
	public void initParams(){
		this.minCount=StrUtil.noeInt(this.conf.getContentByName("minCount"),0);
		this.maxCount=StrUtil.noeInt(this.conf.getContentByName("maxCount"),0);
		this.step=StrUtil.noeInt(this.conf.getContentByName("step"),0);
		this.inPool=new ArrayList<T>();
		this.outPool=new ArrayList<T>();
		addSomeObject(this.minCount);
	}
	
	public synchronized T getObject(){
		int poolSize=this.inPool.size();
		if(poolSize==0){
			this.addSomeObject(this.step);
		}
		int lastIndex=this.inPool.size()-1;
		T o=this.inPool.remove(lastIndex);
		this.outPool.add(o);
		return o;
	}
	
	public synchronized void returnObject(T o){
		if(!this.outPool.contains(o)){
			return;
		}
		if(this.inPool.size()<this.maxCount){
			afterCallback(o);
		}else{
			afterOverFlow(o);
		}
		this.outPool.remove(o);
	}

	protected void afterCallback(T o) {
		this.inPool.add(o);
	}
	
	protected void afterOverFlow(T o){
		System.gc();
	}
	
	public void viewStatus(T o){
		if(this.inPool.contains(o)){
			System.out.println("["+o+"] is in the pool.");
		}else if(this.outPool.contains(o)){
			System.out.println("["+o+"] is in use.");
		}else{
			System.out.println("["+o+"] is out of control.");
		}
	}
	
	public void viewSomeStatus(Iterator<T> it){
		for(;it.hasNext();){
			this.viewStatus(it.next());
		}
	}
	
	public void viewAllStatus(){
		this.viewSomeStatus(this.inPool.iterator());
		this.viewSomeStatus(this.outPool.iterator());
	}
	
	protected void addSomeObject(int count) {
		for(int i=0;i<count;i++){
			if(this.inPool.size()>=this.maxCount){
				return;
			}
			this.inPool.add(newInstance());
		}
	}
	
	@SuppressWarnings("unchecked")
	protected T newInstance(){
		T t=null;
		try {
			t=(T)Class.forName(className).newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return t;
	}
	
	/*
	 * �����Ҫ���ظ÷������������JDBC��
	 */
	protected void beforeInit(){
		
	}
	
}
